﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
namespace JupiterLibrary
{
    public enum LogLevels
    {
        VerboseAll,
        Warning,
        Error,
        Disable
    }

    public enum LogTypes
    {
        LowLevel,
        Inform,
        Warning,
        Error
    }
    /// <summary>
    /// Se utiliza para tener constancia de qué está haciendo el engine. Por defecto saca la información en la consola y en un archivo de texto.
    /// </summary>
    public sealed class Log
    {
        StreamWriter stream;
        string indent;
        LogLevels logLevel;

        public Log(LogLevels level)
        {
            logLevel = level;

            if (logLevel == LogLevels.Disable) return;

            File.Delete("log.txt");

            stream = new StreamWriter("log.txt", true);
        }


        public void Dispose()
        {
            if (stream != null)
            {
                stream.Close();

                stream = null;
            }
        }

        public void InsertIndent()
        {
            indent += '\t';
        }

        public void RemoveIndent()
        {
            indent = indent.Substring(0, indent.Length - 1);
        }

        public bool CheckLogLevel(LogTypes logType)
        {
            if (logLevel == LogLevels.VerboseAll) return true;
            if (logLevel == LogLevels.Disable) return false;

            switch (logType)
            {
                case LogTypes.LowLevel:

                    // To see a LowLevel log, you must set the LogLevel to VerboseAll, so the method will return true at the beginning

                    return false;

                case LogTypes.Inform:
                    
                    if (logLevel == LogLevels.Warning || logLevel==LogLevels.Error) return true;

                    break;

                case LogTypes.Warning:

                    if (logLevel == LogLevels.Warning || logLevel==LogLevels.Error) return true;

                    break;

                case LogTypes.Error:

                    return true;
            }

            return false;

        }

        public bool BeginMethod()
        {
            if (!CheckLogLevel(LogTypes.LowLevel)) return false;

            StackTrace stackTrace = new StackTrace();           // get call stack
            StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)

            // Get the previos methos. The 0 member is the current method(this)
            StackFrame stackFrame = stackFrames[1];

            System.Reflection.MethodBase method = stackFrame.GetMethod();
            
            WriteLine(method.ReflectedType + "." + method.Name);

            WriteLine("{", LogTypes.LowLevel);
            
            InsertIndent();

            return true;
        }

        public void EndMethod()
        {
            RemoveIndent();

            WriteLine("}", LogTypes.LowLevel);
        }

        public void WriteLine(string text,LogTypes logType=LogTypes.Inform)
        {
            if (!CheckLogLevel(logType)) return;

            Console.WriteLine(indent+text);

            stream.WriteLine(indent+text);

            stream.Flush();
        }
    }
}
